// 瓒呮椂妫�娴嬬嚎绋�
package com.thread;

import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import com.databus.*;

public class TimeOutThread implements Runnable {
	
	public TimeOutThread(TimeOutCallBack cb)
	{
		mCb = cb;
		mTimeOutQueueMap = new ConcurrentHashMap<Integer, BlockingQueue<TimeOutItem> >();
	}
	
	// 娣诲姞瓒呮椂妫�娴�
	public void AddTimeOut(int serNum, int milliseconds)
	{
		TimeOutItem item = new TimeOutItem();
		item.serNum = serNum;
		item.endTime = System.currentTimeMillis() + milliseconds;
		item.milliseconds = milliseconds;
		synchronized (mTimeOutQueueMap) {
			if(!mTimeOutQueueMap.containsKey(milliseconds))
			{
				mTimeOutQueueMap.put(milliseconds, new LinkedBlockingQueue<TimeOutItem>());
			}
		}
		mTimeOutQueueMap.get(milliseconds).add(item);
	}

	// 閲嶇疆瓒呮椂
	public void resetAddTimeout(int serNum) {
		BlockingQueue<TimeOutItem> queue = null;
		TimeOutItem i = null;
		for (BlockingQueue<TimeOutItem> entry : mTimeOutQueueMap.values()) {
			for(TimeOutItem item : entry) {
				if (item.serNum == serNum) {
					queue = entry;
					i = item; 
					break;
				}
			}
		}
		if(queue != null && i != null) {
			if(queue.remove(i)) {
				i.endTime = System.currentTimeMillis() + i.milliseconds;
				Log.info("reset timeout,serail:"+i.serNum+",endtime:"+i.endTime);
				queue.add(i);
			}
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Log.info("Start TimeOut Thread...");
		
		while(!Thread.interrupted())
		{
			if(!mTimeOutQueueMap.isEmpty())
			{
				long curTime = System.currentTimeMillis();
				for(Map.Entry<Integer, BlockingQueue<TimeOutItem> > entry : mTimeOutQueueMap.entrySet())
				{
					do
					{
						TimeOutItem item = entry.getValue().peek();
						if(null == item)
						{
							break;
						}
						if(item.endTime < curTime)
						{
							entry.getValue().poll();
							mCb.OnMessageTimeOut(item.serNum);
						}
						else
						{
							break;
						}
					}while(true);
				}
			}
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
//				e.printStackTrace();
				break;
			}
		}
		
		Log.info("End TimeOut Thread...");
	}
	
	class TimeOutItem
	{
		int serNum;        // 娴佹按鍙�
		long endTime;      // 瓒呮椂鏃堕棿鐐�
		long milliseconds; // 瀛樺偍瓒呮椂鏃堕棿,鐢ㄤ簬reset瓒呮椂
	}

	private TimeOutCallBack mCb;                                          // 瓒呮椂鍥炶皟鎺ュ彛
	private Map<Integer, BlockingQueue<TimeOutItem> > mTimeOutQueueMap;    // 瓒呮椂妫�娴媘ap 
}
